package job

import (
	"github.com/robfig/cron"
	"github.com/sirupsen/logrus"
	"hcy-api/lib/utils"
	"hcy-api/structs/constant"
	"hcy-api/structs/tables"
	"idp/global"
	"idp/listener"
	"idp/repository"
	"idp/service"
	"strings"
	"time"
)

func Start() {
	c := cron.New()
	// 每10分钟清理一次任务
	if err := c.AddFunc("@every 5s", checkTask); err != nil {
		logrus.Error(err)
	}
	// 每5分钟通知一次在线的客户端执行未处理的任务,同时也能更好的清理不在线的设备
	if err := c.AddFunc("@every 5s", pushInstruct); err != nil {
		logrus.Error(err)
	}
	c.Start()
}

// checkTask 如果任务已经到了触发时机就加载相关的指令缓存
func checkTask() {
	global.TaskCatch.Range(func(key, value any) bool {
		task := value.(tables.IdpTask)
		if _, err := service.TaskService.LoadInstructByTask(task); err != nil {
			logrus.Error(err)
		}
		return true
	})
}

// pushInstruct 推送已经缓存的指令
func pushInstruct() {
	global.InfoCatchMaoForIdp.Range(func(clientId, value any) bool {
		pm := global.GetClientInstructCatch(clientId.(int64))
		for _, inst := range pm {
			isSend := true
			// 检查是否携带了任务id任务是否已经过期或者被取消
			if inst.Cmd == "file.exe" || inst.Cmd == "process.exe" {
				if strings.HasPrefix(inst.Args[0], "-taskId=") {
					taskId := utils.StrToInt64(strings.ReplaceAll(inst.Args[0], "-taskId=", ""))
					taskObj, catchIsExist := global.TaskCatch.Load(taskId)
					if !catchIsExist {
						// 如果缓存中没有这个任务记录，就查询数据库
						task, err := repository.TaskRepository.FindTaskById(taskId)
						if err != nil {
							logrus.Error(err)
							continue
						}
						var b bool
						b, err = service.TaskService.LoadInstructByTask(task)
						if err != nil {
							logrus.Error(err)
							continue
						}
						if !b {
							isSend = false
							delete(pm, listener.InstructionUtils.GetCatchKey(inst))
							continue
						}
						global.TaskCatch.Store(task.Id, task)
					} else {
						task := taskObj.(tables.IdpTask)
						// 任务存在与缓存中，检查任务是否已经过期，任务状态是否正常，
						if task.Status != tables.IdpTaskStatusForNormal || task.EndTime < time.Now().Unix() {
							isSend = false
							err := service.TaskService.SyncTaskCatch(task)
							if err != nil {
								logrus.Error(err)
							}
							delete(pm, listener.InstructionUtils.GetCatchKey(inst))
							continue
						}
					}
				}
			}
			if isSend {
				_ = listener.SendInstruct(clientId.(int64), constant.ExecutePlugin, inst.Cmd, inst.Args)
				delete(pm, listener.InstructionUtils.GetCatchKey(inst))
			}
		}
		global.SetClientInstructCatch(clientId.(int64), pm)
		return true
	})
}
